package com.yang.trainingCamp.service;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.yang.trainingCamp.dao.*;
import com.yang.trainingCamp.pojo.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReentrantLock;

@Service
public class TimedTaskService {

    @Autowired
    private CampersMapper campersMapper;

    @Autowired
    private CamperProductsMapper camperProductsMapper;

    @Autowired
    private TrainingCampOrderMapper trainingCampOrderMapper;

    @Autowired
    private EntryRecordMapper entryRecordMapper;

    @Autowired
    private CustomerMapper customerMapper;

    @Autowired
    private ProductMapper productMapper;

    @Autowired
    private AdviserMapper adviserMapper;

    @Autowired
    private ObtainedOrderMapper obtainedOrderMapper;

    @Scheduled(cron = "0 1/3 * * * ?")
    @Transactional
    public void automaticEntry() {
        System.out.println("自动入营任务执行！");

        camperProductsMapper.updateCamperProductNumber();

        entryRecordMapper.updateCamperEntryState();
    }

    @Scheduled(cron = "0 1/4 * * * ?")
    @Transactional
    public void continuationBusiness() throws ParseException {
        System.out.println("自动续营任务执行！");

        QueryWrapper<EntryRecord> entryRecordQueryWrapper = new QueryWrapper<>();
        entryRecordQueryWrapper.eq("in_camp", 2);
        entryRecordQueryWrapper.lt("closing_time", new Date());
        List<EntryRecord> entryRecordList = entryRecordMapper.selectList(entryRecordQueryWrapper);
        for (EntryRecord e: entryRecordList) {

            e.setInCamp(3);
            entryRecordMapper.updateById(e);

            QueryWrapper<CamperProducts> camperProductsQueryWrapper = new QueryWrapper<>();
            camperProductsQueryWrapper.eq("camper_id", e.getCamperId()).gt("number", 0).orderByDesc("create_at");
            List<CamperProducts> camperProductList = camperProductsMapper.selectList(camperProductsQueryWrapper);
            if (camperProductList != null && !camperProductList.isEmpty()){

                SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
                Calendar calendar1 = new GregorianCalendar();
                Calendar calendar = new GregorianCalendar();

                EntryRecord entryRecord = new EntryRecord();
                entryRecord.setCamperId(e.getCamperId());
                entryRecord.setCustomerId(e.getCustomerId());
                entryRecord.setCustomerName(e.getCustomerName());
                entryRecord.setInCamp(2);
                calendar1.setTime(sdf.parse(sdf.format(new Date())+" 00:00:00"));
                calendar1.add(Calendar.DATE,1);
                entryRecord.setEntryTime(calendar1.getTime());
                calendar.setTime(entryRecord.getEntryTime());

                /*
                calendar.add(calendar.YEAR, 1);//把日期往后增加一年.整数往后推,负数往前移动
                calendar.add(calendar.DAY_OF_MONTH, 1);//把日期往后增加一个月.整数往后推,负数往前移动
                calendar.add(calendar.DATE,1);//把日期往后增加一天.整数往后推,负数往前移动
                calendar.add(calendar.WEEK_OF_MONTH, 1);//把日期往后增加一个月.整数往后推,负数往前移动
                */

                calendar.add(Calendar.DATE,camperProductList.get(0).getTrainingDays()+1);
                entryRecord.setClosingTime(calendar.getTime());
                entryRecord.setEntryTimeStr(sdf.format(entryRecord.getEntryTime()));
                entryRecord.setClosingTimeStr(sdf.format(calendar.getTime()));
                entryRecord.setCreateAt(new Date());
                entryRecord.setUpdateAt(new Date());
                HashMap<String, Object> newMap = new HashMap<>();
                newMap.put("camper_id", e.getCamperId());
                List<EntryRecord> entryRecordListNew = entryRecordMapper.selectByMap(newMap);
                entryRecord.setFrequency(entryRecordListNew.size()+1);
                entryRecord.setCamperProductId(camperProductList.get(0).getId());
                entryRecord.setProductName(camperProductList.get(0).getProductName());
                entryRecord.setCoachId(e.getCoachId());
                entryRecord.setCoachName(e.getCoachName());
                entryRecord.setRegionId(e.getRegionId());
                entryRecord.setRegionName(e.getRegionName());
                entryRecordMapper.insert(entryRecord);

                Campers camper = new Campers();
                camper.setId(e.getCamperId());
                camper.setCurrentCampTimes(entryRecordListNew.size()+1);
                campersMapper.updateById(camper);

                camperProductList.get(0).setNumber(camperProductList.get(0).getNumber()-1);
                camperProductsMapper.updateById(camperProductList.get(0));
            }
        }
    }

//    需要同步递减
    @Scheduled(cron = "0 1/5 * * * ?")
    @Transactional
    public void continuationBusinessAsync() throws InterruptedException {
        System.out.println("自动续营任务执行！");

        CountDownLatch latch = new CountDownLatch(5);
        ThreadPoolExecutor executor = new ThreadPoolExecutor(5, 6, 1L, TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(6));
//        ReentrantLock reentrantLock = new ReentrantLock();
        for (int i = 1; i < 6; i++) {
            int finalI = i;
            executor.execute(() ->{
                Page<EntryRecord> page = new Page<>(finalI, 3);
                QueryWrapper<EntryRecord> entryRecordQueryWrapper = new QueryWrapper<>();
                entryRecordQueryWrapper.eq("in_camp", 2);
                entryRecordQueryWrapper.lt("closing_time", new Date());
                entryRecordMapper.selectPage(page, entryRecordQueryWrapper);
                List<EntryRecord> entryRecordList = page.getRecords();
//                List<EntryRecord> entryRecordList = entryRecordMapper.selectList(entryRecordQueryWrapper);
                for (EntryRecord e : entryRecordList) {

                    e.setInCamp(3);
                    entryRecordMapper.updateById(e);

//                    reentrantLock.lock();

                    QueryWrapper<CamperProducts> camperProductsQueryWrapper = new QueryWrapper<>();
                    camperProductsQueryWrapper.eq("camper_id", e.getCamperId()).gt("number", 0).orderByDesc("create_at");
                    List<CamperProducts> camperProductList = camperProductsMapper.selectList(camperProductsQueryWrapper);
                    if (camperProductList != null && !camperProductList.isEmpty()) {

                        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
                        Calendar calendar1 = new GregorianCalendar();
                        Calendar calendar = new GregorianCalendar();

                        EntryRecord entryRecord = new EntryRecord();
                        entryRecord.setCamperId(e.getCamperId());
                        entryRecord.setCustomerId(e.getCustomerId());
                        entryRecord.setCustomerName(e.getCustomerName());
                        entryRecord.setInCamp(2);
                        try {
                            calendar1.setTime(sdf.parse(sdf.format(new Date()) + " 00:00:00"));
                        } catch (ParseException parseException) {
                            latch.countDown();
                            parseException.printStackTrace();
                        }
                        calendar1.add(Calendar.DATE, 1);
                        entryRecord.setEntryTime(calendar1.getTime());
                        calendar.setTime(entryRecord.getEntryTime());

                        /*
                        calendar.add(calendar.YEAR, 1);//把日期往后增加一年.整数往后推,负数往前移动
                        calendar.add(calendar.DAY_OF_MONTH, 1);//把日期往后增加一个月.整数往后推,负数往前移动
                        calendar.add(calendar.DATE,1);//把日期往后增加一天.整数往后推,负数往前移动
                        calendar.add(calendar.WEEK_OF_MONTH, 1);//把日期往后增加一个月.整数往后推,负数往前移动
                        */

                        calendar.add(Calendar.DATE, camperProductList.get(0).getTrainingDays() + 1);
                        entryRecord.setClosingTime(calendar.getTime());
                        entryRecord.setEntryTimeStr(sdf.format(entryRecord.getEntryTime()));
                        entryRecord.setClosingTimeStr(sdf.format(calendar.getTime()));
                        entryRecord.setCreateAt(new Date());
                        entryRecord.setUpdateAt(new Date());
                        HashMap<String, Object> newMap = new HashMap<>();
                        newMap.put("camper_id", e.getCamperId());
                        List<EntryRecord> entryRecordListNew = entryRecordMapper.selectByMap(newMap);
                        entryRecord.setFrequency(entryRecordListNew.size() + 1);
                        entryRecord.setCamperProductId(camperProductList.get(0).getId());
                        entryRecord.setProductName(camperProductList.get(0).getProductName());
                        entryRecord.setCoachId(e.getCoachId());
                        entryRecord.setCoachName(e.getCoachName());
                        entryRecord.setRegionId(e.getRegionId());
                        entryRecord.setRegionName(e.getRegionName());
                        entryRecordMapper.insert(entryRecord);

                        Campers camper = new Campers();
                        camper.setId(e.getCamperId());
                        camper.setCurrentCampTimes(entryRecordListNew.size() + 1);
                        campersMapper.updateById(camper);

                        camperProductList.get(0).setNumber(camperProductList.get(0).getNumber() - 1);
                        camperProductsMapper.updateById(camperProductList.get(0));
                    }

//                    reentrantLock.unlock();
                }

                latch.countDown();
            });
        }

        latch.await();
        executor.shutdown();
    }

    @Scheduled(cron = "0 1/2 * * * ?")
    @Transactional
    public void accessProducts(){
        System.out.println("获取营员购买产品任务执行！");

        List<TrainingCampOrder> trainingCampOrderList = trainingCampOrderMapper.queryNotObtainedOrder();
        for (TrainingCampOrder trainingCampOrder: trainingCampOrderList
             ) {
            QueryWrapper<CamperProducts> camperProductsQueryWrapper = new QueryWrapper<>();
            camperProductsQueryWrapper.eq("camper_id", trainingCampOrder.getCamperId());
            List<CamperProducts> camperProductList = camperProductsMapper.selectList(camperProductsQueryWrapper);
            String[] productList = trainingCampOrder.getTrainingCampProducts().split(",");
            if (camperProductList == null){
                for (String s: productList
                     ) {
                    String[] product = s.split("&");
                    CamperProducts newCamperProduct = new CamperProducts();
                    newCamperProduct.setCamperId(trainingCampOrder.getCamperId());
                    newCamperProduct.setProductId(product[0]);
                    newCamperProduct.setProductName(product[1]);
                    newCamperProduct.setTrainingDays(Integer.parseInt(product[2]));
                    newCamperProduct.setNumber(Integer.parseInt(product[3]));
                    newCamperProduct.setCreateAt(new Date());
                    newCamperProduct.setUpdateAt(new Date());
                    camperProductsMapper.insert(newCamperProduct);
                }
            }else {
                for (String s: productList
                ) {
                    String[] product = s.split("&");
                    QueryWrapper<CamperProducts> camperProductsQueryWrapperNew = new QueryWrapper<>();
                    camperProductsQueryWrapperNew.eq("product_id", product[0]).eq("camper_id", trainingCampOrder.getCamperId());
                    CamperProducts camperProductsNew = camperProductsMapper.selectOne(camperProductsQueryWrapperNew);
                    if (camperProductsNew == null){
                        CamperProducts newCamperProduct = new CamperProducts();
                        newCamperProduct.setCamperId(trainingCampOrder.getCamperId());
                        newCamperProduct.setProductId(product[0]);
                        newCamperProduct.setProductName(product[1]);
                        newCamperProduct.setTrainingDays(Integer.parseInt(product[2]));
                        newCamperProduct.setNumber(Integer.parseInt(product[3]));
                        newCamperProduct.setCreateAt(new Date());
                        newCamperProduct.setUpdateAt(new Date());
                        camperProductsMapper.insert(newCamperProduct);
                    }else {
                        camperProductsNew.setNumber(camperProductsNew.getNumber() + Integer.parseInt(product[3]));
                        camperProductsNew.setUpdateAt(new Date());
                        camperProductsMapper.updateById(camperProductsNew);
                    }
                }
            }

            ObtainedOrder obtainedOrder = new ObtainedOrder();
            obtainedOrder.setOrderId(trainingCampOrder.getId());
            obtainedOrder.setCreateAt(new Date());
            obtainedOrder.setUpdateAt(new Date());
            obtainedOrderMapper.insert(obtainedOrder);
        }
    }

//    @Scheduled(cron = "0 1/1 * * * ?")
    @Transactional
    public void accessProductsAsync() throws InterruptedException {
        System.out.println("获取营员购买产品任务执行！");

        CountDownLatch latch = new CountDownLatch(5);
        ThreadPoolExecutor executor = new ThreadPoolExecutor(5, 6, 1L, TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(6));
        ReentrantLock reentrantLock = new ReentrantLock();
        for (int i = 0; i < 5; i++) {
            int finalI = i;
            executor.execute(() -> {
                List<TrainingCampOrder> trainingCampOrderList = trainingCampOrderMapper.queryNotObtainedOrderAync(finalI * 3);
                for (TrainingCampOrder trainingCampOrder : trainingCampOrderList
                ) {
                    QueryWrapper<CamperProducts> camperProductsQueryWrapper = new QueryWrapper<>();
                    camperProductsQueryWrapper.eq("camper_id", trainingCampOrder.getCamperId());
                    List<CamperProducts> camperProductList = camperProductsMapper.selectList(camperProductsQueryWrapper);
                    String[] productList = trainingCampOrder.getTrainingCampProducts().split(",");
                    if (camperProductList == null) {
                        for (String s : productList
                        ) {
                            String[] product = s.split("&");
                            CamperProducts newCamperProduct = new CamperProducts();
                            newCamperProduct.setCamperId(trainingCampOrder.getCamperId());
                            newCamperProduct.setProductId(product[0]);
                            newCamperProduct.setProductName(product[1]);
                            newCamperProduct.setTrainingDays(Integer.parseInt(product[2]));
                            newCamperProduct.setNumber(Integer.parseInt(product[3]));
                            newCamperProduct.setCreateAt(new Date());
                            newCamperProduct.setUpdateAt(new Date());
                            camperProductsMapper.insert(newCamperProduct);
                        }
                    } else {
                        for (String s : productList
                        ) {
                            reentrantLock.lock();

                            String[] product = s.split("&");
                            QueryWrapper<CamperProducts> camperProductsQueryWrapperNew = new QueryWrapper<>();
                            camperProductsQueryWrapperNew.eq("product_id", product[0]).eq("camper_id", trainingCampOrder.getCamperId());
                            CamperProducts camperProductsNew = camperProductsMapper.selectOne(camperProductsQueryWrapperNew);
                            if (camperProductsNew == null) {
                                CamperProducts newCamperProduct = new CamperProducts();
                                newCamperProduct.setCamperId(trainingCampOrder.getCamperId());
                                newCamperProduct.setProductId(product[0]);
                                newCamperProduct.setProductName(product[1]);
                                newCamperProduct.setTrainingDays(Integer.parseInt(product[2]));
                                newCamperProduct.setNumber(Integer.parseInt(product[3]));
                                newCamperProduct.setCreateAt(new Date());
                                newCamperProduct.setUpdateAt(new Date());
                                camperProductsMapper.insert(newCamperProduct);
                            } else {
                                camperProductsNew.setNumber(camperProductsNew.getNumber() + Integer.parseInt(product[3]));
                                camperProductsNew.setUpdateAt(new Date());
                                camperProductsMapper.updateById(camperProductsNew);
                            }

                            reentrantLock.unlock();
                        }
                    }

                    ObtainedOrder obtainedOrder = new ObtainedOrder();
                    obtainedOrder.setOrderId(trainingCampOrder.getId());
                    obtainedOrder.setCreateAt(new Date());
                    obtainedOrder.setUpdateAt(new Date());
                    obtainedOrderMapper.insert(obtainedOrder);
                }

                latch.countDown();
            });
        }

        latch.await();
        executor.shutdown();
    }

//    @Scheduled(cron = "0 1/1 * * * ?")
//    public void insertInfo() throws ParseException {
////        for (int i = 0; i < 5; i++) {
////            Customer customer = new Customer();
////            customer.setName("客户"+Integer.toString(i));
////            customer.setCreateAt(new Date());
////            customer.setUpdateAt(new Date());
////            customerMapper.insert(customer);
////        }
////
////        for (int i = 0; i < 5; i++) {
////            Product product = new Product();
////            product.setName("训练营产品"+Integer.toString(i));
////            product.setTrainingDays(i+6);
////            product.setCreateAt(new Date());
////            product.setUpdateAt(new Date());
////            productMapper.insert(product);
////        }
//
////            Campers camper = new Campers();
////            camper.setCustomerId("4b9a4207e95077370a44bd0fb8f237af");
////            camper.setCustomerName("客户0");
////            camper.setCurrentCampTimes(1);
////            camper.setCreateAt(new Date());
////            camper.setUpdateAt(new Date());
////            campersMapper.insert(camper);
////
////            Campers camper1 = new Campers();
////            camper1.setCustomerId("8ce6cb811e31483eb6badfd192e3fef2");
////            camper1.setCustomerName("客户3");
////            camper1.setCurrentCampTimes(1);
////            camper1.setCreateAt(new Date());
////            camper1.setUpdateAt(new Date());
////            campersMapper.insert(camper1);
//
////        for (int i = 0; i < 5; i++) {
////            Adviser adviser = new Adviser();
////            adviser.setName("顾问"+Integer.toString(i));
////            adviser.setCreateAt(new Date());
////            adviser.setUpdateAt(new Date());
////            adviserMapper.insert(adviser);
////        }
//
////        TrainingCampOrder trainingCampOrder = new TrainingCampOrder();
////        trainingCampOrder.setType(8);
////        trainingCampOrder.setCustomerId("8ce6cb811e31483eb6badfd192e3fef2");
////        trainingCampOrder.setCustomerName("客户3");
////        trainingCampOrder.setNextPersonId("cae48935472ab7243c2a99632840906e");
////        trainingCampOrder.setNextPersonName("顾问1");
////        trainingCampOrder.setTrainingCampProducts("a4c308fe693c6209675ee18b1848ca11&训练营产品2&8&3,ca5cb6d268ea37d74d275a9495e8631e&训练营产品0&6&4,db5fd8cef34cf47eb31195ff81344514&训练营产品1&7&2,21664e4d7cdceef848f0707524d7cc38&训练营产品4&10&1");
////        trainingCampOrder.setState(1);
////        trainingCampOrder.setCreateAt(new Date());
////        trainingCampOrder.setUpdateAt(new Date());
////        trainingCampOrderMapper.insert(trainingCampOrder);
//
//        EntryRecord entryRecord = new EntryRecord();
//        entryRecord.setCamperId("81d58b8586c27ea03a9e0c702693465a");
//        entryRecord.setCustomerId("4b9a4207e95077370a44bd0fb8f237af");
//        entryRecord.setCustomerName("客户0");
//        entryRecord.setInCamp(2);
//        entryRecord.setEntryTimeStr("2021-06-23");
//        entryRecord.setClosingTimeStr("2021-07-23");
//        entryRecord.setCamperProductId("3a747e9ca26457905fb814f4bd905f08");
//        entryRecord.setProductName("训练营产品2");
//        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
//        entryRecord.setEntryTime(sdf.parse(entryRecord.getEntryTimeStr()+" 00:00:00"));
//        entryRecord.setClosingTime(sdf.parse(entryRecord.getClosingTimeStr()+" 00:00:00"));
//        entryRecord.setFrequency(1);
//        entryRecord.setCreateAt(new Date());
//        entryRecord.setUpdateAt(new Date());
//        entryRecordMapper.insert(entryRecord);
//
//        System.out.println("Id生成执行！");
//    }
}
